Zucker SOCで有機ELディスプレイを動かしたい
ピン
clk(シリアルクロック)
mosi
シリアルクロックのライジングエッジの度にD7、D6、D5 ... D0と読み込む
dc
high→データとして解釈
low→コマンドとして解釈
resn(リセットの負論理信号)
LOWにするとリセット
基本はHIGHにしておく
csn(チップセレクトの負論理信号)
code:ulx3s_v20.lpf
## SPI OLED DISPLAY SSD1331 (Color) or SSD1306 (B/W) "blinkey", "usb" sheet
LOCATE COMP "oled_clk" SITE "P4";
LOCATE COMP "oled_mosi" SITE "P3";
LOCATE COMP "oled_dc" SITE "P1";
LOCATE COMP "oled_resn" SITE "P2";
LOCATE COMP "oled_csn" SITE "N2";
IOBUF PORT "oled_clk" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "oled_mosi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "oled_dc" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "oled_resn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "oled_csn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
FemtoRVのメモリマップトIO
IOベースアドレス
code:FIRMWARE/LIBFEMTORV32/femtorv32.inc
.equ IO_BASE, 0x400000 # Base address of memory-mapped IO
IOベース + N
code:FemtoRV/FIRMWARE/LIBFEMTORV32/HardwareConfig_bits.inc
# IO_XXX = 1 << (IO_XXX_bit + 2)
.equ IO_LEDS, 4
.equ IO_UART_DAT, 8
.equ IO_UART_CNTL, 16
.equ IO_SSD1351_CNTL, 32
.equ IO_SSD1351_CMD, 64
.equ IO_SSD1351_DAT, 128
.equ IO_SSD1351_DAT16, 256
.equ IO_MAX7219_DAT, 512
.equ IO_SDCARD, 1024
.equ IO_BUTTONS, 2048
やりたいこと
電源オン
画面全体を黒で塗りつぶし
画面全体を白で塗りつぶし
別な色で塗りつぶし
メモリ上の画像データを描画
電源オン
code:asm
.equ IO_BASE, 0x400000
.equ IO_SSD1351_CMD, 64
li gp, IO_BASE
li t0, 0xaf // 電源オン
sw t0, IO_SSD1351_CMD(gp)
これでも良さそう
code:asm
li t0, 0x400040
li t1, 0xaf
sw t1, t0
【参考になりそう】FemtoRVのコード
code:FemtoRV/FIRMWARE/LIBFEMTORV32/ssd1351_1331_init.S
# initialize oled display
.global oled_init
.type oled_init, @function
oled_init:
add sp,sp,-4
sw ra, 0(sp)
.ifdef SSD1331
OLED0 0xae # display off
OLED1 0x81, 0x91 # contrast A
OLED1 0x82, 0x50 # contrast B
OLED1 0x83, 0x7d # contrast C
OLED1 0x87, 0x06 # master current control
OLED1 0x8a, 0x64 # prechargeA
OLED1 0x8b, 0x78 # prechargeB
OLED1 0x8c, 0x64 # prechargeC
OLED1 0xa0, 0x60 # RGB mode and remap
OLED1 0xa1, 0x00 # startline
OLED1 0xa2, 0x00 # display offset
OLED0 0xa4 # normal display
OLED1 0xa8, 0x3f # set multiplex
OLED1 0xad, 0x8e # set master
OLED1 0xb0, 0x00 # powersave mode
OLED1 0xb1, 0x31 # phase period adjustment
OLED1 0xb3, 0xf0 # clock div
OLED1 0xbb, 0x3a # prechargelevel
OLED1 0xbe, 0x3e # vcomh
OLED0 0x2e # disable scrolling
OLED0 0xaf # display on
.endif
lw ra, 0(sp)
add sp,sp,4
ret
code:FemtoRV/FIRMWARE/LIBFEMTORV32/ssd1351_1331.inc
.macro OLED0 cmd
li a0,\cmd
call oled0
.endm
.macro OLED1 cmd,arg1
li a0,\cmd
li a1,\arg1
call oled1
.endm
.macro OLED2 cmd,arg1,arg2
li a0,\cmd
li a1,\arg1
li a2,\arg2
call oled2
.endm
.macro OLED3 cmd,arg1,arg2,arg3
li a0,\cmd
li a1,\arg1
li a2,\arg2
li a3,\arg3
call oled3
.endm
code:FemtoRV/FIRMWARE/LIBFEMTORV32/ssd1351_1331.S
#############################################################
# Oled display command, 0 argument, command in a0
.global oled0
.type oled0, @function
oled0: add sp,sp,-4
sw ra, 0(sp)
sw a0, IO_SSD1351_CMD(gp)
lw ra, 0(sp)
add sp,sp,4
ret
#################### Commands for SSD1331 #########################
.ifdef SSD1331
# Note: unlike SSD1351, command args are sent to CMD, not DAT !
# Oled display command, 1 argument, command in a0, arg in a1
.global oled1
.type oled1, @function
oled1: add sp,sp,-4
sw ra, 0(sp)
sw a0, IO_SSD1351_CMD(gp)
sw a1, IO_SSD1351_CMD(gp)
lw ra, 0(sp)
add sp,sp,4
ret
# Oled display command, 2 arguments, command in a0, args in a1,a2
.global oled2
.type oled2, @function
oled2: add sp,sp,-4
sw ra, 0(sp)
sw a0, IO_SSD1351_CMD(gp)
sw a1, IO_SSD1351_CMD(gp)
sw a2, IO_SSD1351_CMD(gp)
lw ra, 0(sp)
add sp,sp,4
ret
# Oled display command, 3 arguments, command in a0, args in a1,a2,a3
.global oled3
.type oled3, @function
oled3: add sp,sp,-4
sw ra, 0(sp)
sw a0, IO_SSD1351_CMD(gp)
sw a1, IO_SSD1351_CMD(gp)
sw a2, IO_SSD1351_CMD(gp)
sw a3, IO_SSD1351_CMD(gp)
lw ra, 0(sp)
add sp,sp,4
ret
.endif
code:FemtoRV/FIRMWARE/LIBFEMTORV32/HardwareConfig_bits.inc
.equ IO_LEDS, 4
.equ IO_UART_DAT, 8
.equ IO_UART_CNTL, 16
.equ IO_SSD1351_CNTL, 32
.equ IO_SSD1351_CMD, 64
.equ IO_SSD1351_DAT, 128
.equ IO_SSD1351_DAT16, 256
.equ IO_MAX7219_DAT, 512
.equ IO_SDCARD, 1024
.equ IO_BUTTONS, 2048
.equ IO_FGA_CNTL, 4096
.equ IO_FGA_DAT, 8192
.equ IO_HW_CONFIG_RAM, 524288
.equ IO_HW_CONFIG_DEVICES, 1048576
.equ IO_HW_CONFIG_CPUINFO, 2097152
.equ IO_MAPPED_SPI_FLASH, 4194304
code:FemtoRV/FIRMWARE/LIBFEMTORV32/femtorv32.h
/********************* Memory-mapped IO *******************************************************/
#define IO_BASE 0x400000 /* Base address of memory-mapped IO */ /* Converts a memory-mapped register bit into the corresponding offset to be added to IO_BASE */
#define IO_BIT_TO_OFFSET(io_bit) (1 << (2+(io_bit))) /* All the memory-mapped hardware registers */
#define IO_LEDS IO_BIT_TO_OFFSET(IO_LEDS_bit) #define IO_SSD1351_CNTL IO_BIT_TO_OFFSET(IO_SSD1351_CNTL_bit) #define IO_SSD1351_CMD IO_BIT_TO_OFFSET(IO_SSD1351_CMD_bit) #define IO_SSD1351_DAT IO_BIT_TO_OFFSET(IO_SSD1351_DAT_bit) #define IO_SSD1351_DAT16 IO_BIT_TO_OFFSET(IO_SSD1351_DAT16_bit) #define IO_UART_CNTL IO_BIT_TO_OFFSET(IO_UART_CNTL_bit) #define IO_UART_DAT IO_BIT_TO_OFFSET(IO_UART_DAT_bit) #define IO_MAX7219 IO_BIT_TO_OFFSET(IO_MAX7219_DAT_bit) #define IO_SPI_FLASH IO_BIT_TO_OFFSET(IO_SPI_FLASH_bit) #define IO_SDCARD IO_BIT_TO_OFFSET(IO_SDCARD_bit) #define IO_BUTTONS IO_BIT_TO_OFFSET(IO_BUTTONS_bit) #define IO_FGA_CNTL IO_BIT_TO_OFFSET(IO_FGA_CNTL_bit) #define IO_FGA_DAT IO_BIT_TO_OFFSET(IO_FGA_DAT_bit) #define IO_HW_CONFIG_RAM IO_BIT_TO_OFFSET(IO_HW_CONFIG_RAM_bit) #define IO_HW_CONFIG_DEVICES IO_BIT_TO_OFFSET(IO_HW_CONFIG_DEVICES_bit) #define IO_HW_CONFIG_CPUINFO IO_BIT_TO_OFFSET(IO_HW_CONFIG_CPUINFO_bit) #define IO_IN(port) *(volatile uint32_t*)(IO_BASE + port) #define IO_OUT(port,val) *(volatile uint32_t*)(IO_BASE + port)=(val) #define LEDS(val) IO_OUT(IO_LEDS,val) #define FEMTOSOC_HAS_DEVICE(bit) (IO_IN(IO_HW_CONFIG_DEVICES) & (1 << bit)) #define FEMTORV32_FREQ ((IO_IN(IO_HW_CONFIG_CPUINFO) >> 16) & 1023) #define FEMTORV32_COUNTER_BITS (IO_IN(IO_HW_CONFIG_CPUINFO) & 127) /* SSD1331/SSD1351 Oled display on 4-wire SPI bus */
アセンブラの時はこっちかも。
code:FemtoRV/FIRMWARE/LIBFEMTORV32/femtorv32.inc
#################################################################################
# Mapped IO constants
.equ IO_BASE, 0x400000 # Base address of memory-mapped IO
.include "HardwareConfig_bits.inc" # generated from RTL/DEVICES/HardwareConfig_bits.v
################################################################################
gp へ IO_BASE をセットするコード
code:FemtoRV/FIRMWARE/CRT/crt0_baremetal.S
.include "femtorv32.inc"
.text
.global _start
.type _start, @function
_start:
.option push
.option norelax
li gp,IO_BASE # Base address of memory-mapped IO
.option pop
li t0,IO_HW_CONFIG_RAM # Can't use IO_HW_CONFIG_RAM(gp) (too far away !)
add t0,t0,gp # Read RAM size in hw config register and
lw sp,0(t0) # initialize SP at end of RAM
li t0,0 # reset t0 to 0
# TODO: clear BSS (for this we need a linker script that declares _edata)
# la t1,_edata
# addi t1,t1,4
# bne t1,sp,.L1
call main
tail exit
参考
ulx3s-exmples / VisualMicro-SSD1331-Display